﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Collections;
using System.Security.Permissions;
using System.Threading;

namespace IRC.IRepairClouds.DataLayer
{
    partial class MultiKeyDictionary<TKey, TValue>
    {
        //[Serializable, DebuggerTypeProxy(typeof(Mscorlib_DictionaryValueCollectionDebugView<,>)), DebuggerDisplay("Count = {Count}")]
        public sealed class ValueCollection
            : ICollection<TValue>,
            IEnumerable<TValue>,
            ICollection,
            IEnumerable
        {
            private MultiKeyDictionary<TKey, TValue> dictionary;

            public ValueCollection(MultiKeyDictionary<TKey, TValue> dictionary)
            {
                if (dictionary == null) {
                    throw new ArgumentNullException();
                    //ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
                }
                this.dictionary = dictionary;
            }

            public void CopyTo(TValue[] array, int index)
            {
                if (array == null) {
                    throw new ArgumentNullException();
                    //ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
                }
                if ((index < 0) || (index > array.Length)) {
                    throw new ArgumentOutOfRangeException();
                    //ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
                }
                if ((array.Length - index) < this.dictionary.ValueCount) {
                    throw new ArgumentException();
                    //ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
                }
                int count = this.dictionary.valCount;
                MultiKeyDictionary<TKey, TValue>.ValEntry[] entries = this.dictionary.valEntries;
                for (int i = 0; i < count; i++) {
                    if (entries[i].valid) {
                        array[index++] = entries[i].value;
                    }
                }
            }

            public Enumerator GetEnumerator()
            {
                return new Enumerator(this.dictionary);
            }

            void ICollection<TValue>.Add(TValue item)
            {
                throw new NotSupportedException();
                //ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet);
            }

            void ICollection<TValue>.Clear()
            {
                throw new NotSupportedException();
                //ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet);
            }

            bool ICollection<TValue>.Contains(TValue item)
            {
                return this.dictionary.ContainsValue(item);
            }

            bool ICollection<TValue>.Remove(TValue item)
            {
                throw new NotSupportedException();
                //ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet);
                //return false;
            }

            IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator()
            {
                return new Enumerator(this.dictionary);
            }

            void ICollection.CopyTo(Array array, int index)
            {
                if (array == null) {
                    throw new ArgumentNullException();
                    //ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
                }
                if (array.Rank != 1) {
                    throw new ArgumentException();
                    //ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
                }
                if (array.GetLowerBound(0) != 0) {
                    throw new ArgumentException();
                    //ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
                }
                if ((index < 0) || (index > array.Length)) {
                    throw new ArgumentOutOfRangeException();
                    //ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
                }
                if ((array.Length - index) < this.dictionary.ValueCount) {
                    throw new ArgumentException();
                    //ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
                }
                TValue[] localArray = array as TValue[];
                if (localArray != null) {
                    this.CopyTo(localArray, index);
                }
                else {
                    object[] objArray = array as object[];
                    if (objArray == null) {
                        throw new ArgumentException();
                        //ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
                    }
                    int count = this.dictionary.valCount;
                    MultiKeyDictionary<TKey, TValue>.ValEntry[] entries = this.dictionary.valEntries;
                    try {
                        for (int i = 0; i < count; i++) {
                            if (entries[i].valid) {
                                objArray[index++] = entries[i].value;
                            }
                        }
                    }
                    catch (ArrayTypeMismatchException) {
                        throw new ArgumentException();
                        //ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
                    }
                }
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return new Enumerator(this.dictionary);
            }

            // Properties
            public int Count
            {
                get
                {
                    return this.dictionary.ValueCount;
                }
            }

            bool ICollection<TValue>.IsReadOnly
            {
                get
                {
                    return true;
                }
            }

            bool ICollection.IsSynchronized
            {
                get
                {
                    return false;
                }
            }

            object ICollection.SyncRoot
            {
                get
                {
                    return ((ICollection)this.dictionary).SyncRoot;
                }
            }

            [Serializable]
            public struct Enumerator
                : IEnumerator<TValue>,
                IDisposable,
                IEnumerator
            {
                private MultiKeyDictionary<TKey, TValue> dictionary;
                private int index;
                private int version;
                private TValue currentValue;
                internal Enumerator(MultiKeyDictionary<TKey, TValue> dictionary)
                {
                    this.dictionary = dictionary;
                    this.version = dictionary.version;
                    this.index = 0;
                    this.currentValue = default(TValue);
                }

                public void Dispose()
                {
                }

                public bool MoveNext()
                {
                    if (this.version != this.dictionary.version) {
                        throw new InvalidOperationException();
                        //ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
                    }
                    while (this.index < this.dictionary.valCount) {
                        if (this.dictionary.valEntries[this.index].valid) {
                            this.currentValue = this.dictionary.valEntries[this.index].value;
                            this.index++;
                            return true;
                        }
                        this.index++;
                    }
                    this.index = this.dictionary.valCount + 1;
                    this.currentValue = default(TValue);
                    return false;
                }

                public TValue Current
                {
                    get
                    {
                        return this.currentValue;
                    }
                }
                object IEnumerator.Current
                {
                    get
                    {
                        if ((this.index == 0) || (this.index == (this.dictionary.valCount + 1))) {
                            throw new InvalidOperationException();
                            //ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
                        }
                        return this.currentValue;
                    }
                }
                void IEnumerator.Reset()
                {
                    if (this.version != this.dictionary.version) {
                        throw new InvalidOperationException();
                        //ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
                    }
                    this.index = 0;
                    this.currentValue = default(TValue);
                }
            }
        }
    }
}
